package com.wenx.v3system.modular.cloud.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wenx.v3core.error.BusinessException;
import com.wenx.v3system.modular.cloud.mapper.SysPermissionConditionMapper;
import com.wenx.v3system.modular.cloud.domain.dto.SysPermissionConditionDto;
import com.wenx.v3system.modular.cloud.domain.maps.SysPermissionConditionMap;
import com.wenx.v3system.modular.cloud.domain.po.SysPermissionCondition;
import com.wenx.v3system.modular.cloud.domain.query.SysPermissionConditionQuery;
import com.wenx.v3system.modular.cloud.service.SysPermissionConditionRestService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 系统权限条件服务实现类
 * 整合了Rest服务和缓存服务功能，遵循Service层职责规范
 * 负责权限条件的CRUD操作、缓存管理、业务逻辑处理
 * 
 * @author wenx
 * @since 1.0.0
 */
@Slf4j
@Service
public class SysPermissionConditionRestServiceImpl extends ServiceImpl<SysPermissionConditionMapper, SysPermissionCondition>
        implements SysPermissionConditionRestService{

    private final SysPermissionConditionMap permissionConditionMap;
    
    /**
     * 构造函数注入，遵循用户偏好的依赖注入方式
     */
    public SysPermissionConditionRestServiceImpl(SysPermissionConditionMap permissionConditionMap) {
        this.permissionConditionMap = permissionConditionMap;
    }
    
    // ============= 缓存服务接口实现 =============
    
    @Override
    @Cacheable(value = "permission:conditions:table", key = "'table:' + #tableName", unless = "#result.isEmpty()")
    public List<SysPermissionCondition> getByTableName(String tableName) {
        if (tableName == null) {
            return Collections.emptyList();
        }
        
        log.debug("从数据库加载表 {} 的权限条件", tableName);
        return loadByTableName(tableName);
    }

    @Override
    @Cacheable(value = "permission:conditions", key = "'permission:' + #permissionId", unless = "#result.isEmpty()")
    public List<SysPermissionCondition> getByPermissionId(Long permissionId) {
        if (permissionId == null) {
            return Collections.emptyList();
        }
        
        log.debug("从数据库加载权限 {} 的条件", permissionId);
        return loadByPermissionId(permissionId);
    }

    @Override
    @CacheEvict(value = "permission:conditions:table", key = "'table:' + #tableName")
    public void refreshTableCache(String tableName) {
        log.debug("清除表 {} 的权限条件缓存", tableName);
    }

    @Override
    @CacheEvict(value = "permission:conditions", key = "'permission:' + #permissionId")
    public void refreshPermissionCache(Long permissionId) {
        log.debug("清除权限 {} 的条件缓存", permissionId);
    }

    @Override
    @CacheEvict(value = {"permission:conditions", "permission:conditions:table"}, allEntries = true)
    public void refreshAllCache() {
        log.info("清空所有权限条件缓存");
    }

    @Override
    public void preloadCache() {
        // Redis缓存模式下，不需要预加载
        log.debug("Redis缓存模式，跳过预加载");
    }
    
    // ============= 缓存辅助方法 =============
    
    /**
     * 从数据库加载指定表的权限条件
     */
    private List<SysPermissionCondition> loadByTableName(String tableName) {
        LambdaQueryWrapper<SysPermissionCondition> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysPermissionCondition::getTableName, tableName)
               .eq(SysPermissionCondition::getStatus, 1)
               .orderByAsc(SysPermissionCondition::getSort);
        
        List<SysPermissionCondition> conditions = list(wrapper);
        return conditions != null ? conditions : Collections.emptyList();
    }
    
    /**
     * 从数据库加载指定权限的条件
     */
    private List<SysPermissionCondition> loadByPermissionId(Long permissionId) {
        LambdaQueryWrapper<SysPermissionCondition> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysPermissionCondition::getPermissionId, permissionId)
               .eq(SysPermissionCondition::getStatus, 1)
               .orderByAsc(SysPermissionCondition::getSort);
        
        List<SysPermissionCondition> conditions = list(wrapper);
        return conditions != null ? conditions : Collections.emptyList();
    }
    
    // ============= RestService接口实现 =============
    
    @Override
    public IPage<?> page(SysPermissionConditionQuery query) {
        // 创建分页对象
        Page<SysPermissionCondition> page = new Page<>(query.getCurrent(), query.getSize());
        
        LambdaQueryWrapper<SysPermissionCondition> wrapper = new LambdaQueryWrapper<>();
        
        if (query.getPermissionId() != null) {
            wrapper.eq(SysPermissionCondition::getPermissionId, query.getPermissionId());
        }
        if (StringUtils.hasText(query.getField())) {
            wrapper.like(SysPermissionCondition::getField, query.getField());
        }
        if (StringUtils.hasText(query.getOperator())) {
            wrapper.eq(SysPermissionCondition::getOperator, query.getOperator());
        }
        if (StringUtils.hasText(query.getType())) {
            wrapper.eq(SysPermissionCondition::getType, query.getType());
        }
        if (query.getStatus() != null) {
            wrapper.eq(SysPermissionCondition::getStatus, query.getStatus());
        }
        if (StringUtils.hasText(query.getDescription())) {
            wrapper.like(SysPermissionCondition::getDescription, query.getDescription());
        }
        
        wrapper.orderByDesc(SysPermissionCondition::getSort, SysPermissionCondition::getCreateTime);
        
        IPage<SysPermissionCondition> result = super.page(page, wrapper);
        
        // 手动转换为DTO
        Page<SysPermissionConditionDto> dtoPage = new Page<>(result.getCurrent(), result.getSize(), result.getTotal());
        List<SysPermissionConditionDto> dtoList = result.getRecords().stream()
                .map(permissionConditionMap::toDto)
                .collect(Collectors.toList());
        dtoPage.setRecords(dtoList);
        
        return dtoPage;
    }

    @Override
    public Object get(Serializable id) {
        if (id == null) {
            return null;
        }
        Long entityId = Long.valueOf(id.toString());
        SysPermissionCondition entity = getById(entityId);
        return entity != null ? permissionConditionMap.toDto(entity) : null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(SysPermissionConditionDto dto) {
        if (dto.getPermissionId() == null) {
            throw new BusinessException("权限ID不能为空");
        }
        if (!StringUtils.hasText(dto.getField())) {
            throw new BusinessException("条件字段不能为空");
        }
        if (!StringUtils.hasText(dto.getOperator())) {
            throw new BusinessException("操作符不能为空");
        }
        
        if (existsByFieldAndOperator(dto.getPermissionId(), dto.getField(), dto.getOperator(), null)) {
            throw new BusinessException("该权限下已存在相同的字段和操作符组合");
        }
        
        SysPermissionCondition entity = permissionConditionMap.toEntity(dto);
        
        if (entity.getSort() == null) {
            Long maxSort = getMaxSort(dto.getPermissionId());
            entity.setSort(maxSort + 1);
        }
        
        save(entity);
        
        // 刷新缓存
        refreshRelatedCache(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(SysPermissionConditionDto dto) {
        if (dto.getId() == null) {
            throw new BusinessException("权限条件ID不能为空");
        }
        
        SysPermissionCondition existingEntity = getById(dto.getId());
        if (existingEntity == null) {
            throw new BusinessException("权限条件不存在，ID: " + dto.getId());
        }
        
        if (StringUtils.hasText(dto.getField()) && StringUtils.hasText(dto.getOperator())) {
            if (existsByFieldAndOperator(dto.getPermissionId(), dto.getField(), dto.getOperator(), dto.getId())) {
                throw new BusinessException("该权限下已存在相同的字段和操作符组合");
            }
        }
        
        SysPermissionCondition entity = permissionConditionMap.toEntity(dto);
        updateById(entity);
        
        // 刷新缓存（包括旧的表名和新的表名）
        refreshRelatedCache(existingEntity);
        refreshRelatedCache(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Serializable id) {
        if (id == null) {
            throw new BusinessException("权限条件ID不能为空");
        }
        Long entityId = Long.valueOf(id.toString());
        SysPermissionCondition entity = getById(entityId);
        if (entity != null) {
            removeById(entityId);
            // 刷新缓存
            refreshRelatedCache(entity);
        }
    }

    // RestService中的业务方法，返回DTO
    @Override
    public List<SysPermissionConditionDto> getByPermissionIdAsDto(Long permissionId) {
        List<SysPermissionCondition> conditions = getByPermissionId(permissionId);
        return permissionConditionMap.toDtoList(conditions);
    }
    
    @Override
    public List<SysPermissionConditionDto> getByTableNameAsDto(String tableName) {
        List<SysPermissionCondition> conditions = getByTableName(tableName);
        return permissionConditionMap.toDtoList(conditions);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByPermissionId(Long permissionId) {
        // 先查询要删除的条件，用于后续刷新缓存
        List<SysPermissionCondition> existingConditions = list(
                new LambdaQueryWrapper<SysPermissionCondition>()
                        .eq(SysPermissionCondition::getPermissionId, permissionId)
        );
        
        LambdaQueryWrapper<SysPermissionCondition> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysPermissionCondition::getPermissionId, permissionId);
        remove(wrapper);
        
        // 刷新缓存 - 直接调用自身的缓存方法
        refreshPermissionCache(permissionId);
        existingConditions.forEach(this::refreshRelatedCache);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchUpdateSort(List<Long> conditionIds) {
        Set<String> affectedTableNames = new HashSet<>();
        Set<Long> affectedPermissionIds = new HashSet<>();
        
        for (int i = 0; i < conditionIds.size(); i++) {
            Long conditionId = conditionIds.get(i);
            SysPermissionCondition existingCondition = getById(conditionId);
            if (existingCondition != null) {
                if (existingCondition.getTableName() != null) {
                    affectedTableNames.add(existingCondition.getTableName());
                }
                if (existingCondition.getPermissionId() != null) {
                    affectedPermissionIds.add(existingCondition.getPermissionId());
                }
            }
            
            SysPermissionCondition condition = new SysPermissionCondition();
            condition.setId(conditionId);
            condition.setSort((long) (i + 1));
            updateById(condition);
        }
        
        // 批量刷新缓存 - 直接调用自身的缓存方法
        affectedTableNames.forEach(this::refreshTableCache);
        affectedPermissionIds.forEach(this::refreshPermissionCache);
    }

    @Override
    public boolean validateConditions(Long permissionId, Object context) {
        List<SysPermissionConditionDto> conditions = getByPermissionIdAsDto(permissionId);
        if (conditions.isEmpty()) {
            return true;
        }
        
        for (SysPermissionConditionDto condition : conditions) {
            if (!validateSingleCondition(condition, context)) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * 验证单个权限条件
     * 
     * @param condition 权限条件
     * @param context 上下文对象
     * @return 验证结果
     */
    private boolean validateSingleCondition(SysPermissionConditionDto condition, Object context) {
        if (context == null) {
            return false;
        }
        
        Object contextValue = getContextValue(condition, context);
        Object conditionValue = getConditionValue(condition);
        
        if (contextValue == null || conditionValue == null) {
            return false;
        }
        
        return evaluateCondition(contextValue, conditionValue, condition.getOperator());
    }
    
    /**
     * 从上下文中获取值
     */
    private Object getContextValue(SysPermissionConditionDto condition, Object context) {
        if (!StringUtils.hasText(condition.getContextField())) {
            return null;
        }
        
        // 使用反射从上下文对象中获取值
        // 支持嵌套属性访问，如 user.departmentId
        String[] fieldPath = condition.getContextField().split("\\.");
        Object currentValue = context;
        
        for (String field : fieldPath) {
            if (currentValue == null) {
                return null;
            }
            currentValue = getFieldValue(currentValue, field);
        }
        
        return currentValue;
    }
    
    /**
     * 获取条件值
     */
    private Object getConditionValue(SysPermissionConditionDto condition) {
        // 优先使用固定值，否则使用上下文字段值
        return StringUtils.hasText(condition.getValue()) ? condition.getValue() : null;
    }
    
    /**
     * 使用反射获取对象字段值
     */
    private Object getFieldValue(Object obj, String fieldName) {
        try {
            java.lang.reflect.Field field = obj.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(obj);
        } catch (Exception e) {
            return null;
        }
    }
    
    /**
     * 根据操作符评估条件
     */
    private boolean evaluateCondition(Object contextValue, Object conditionValue, String operator) {
        String contextStr = String.valueOf(contextValue);
        String conditionStr = String.valueOf(conditionValue);
        
        switch (operator) {
            case "=":
                return contextStr.equals(conditionStr);
            case "!=":
                return !contextStr.equals(conditionStr);
            case "contains":
                return contextStr.contains(conditionStr);
            case "like":
                return contextStr.toLowerCase().contains(conditionStr.toLowerCase());
            case "in":
                String[] values = conditionStr.split(",");
                for (String value : values) {
                    if (contextStr.equals(value.trim())) {
                        return true;
                    }
                }
                return false;
            case "not_in":
                String[] notValues = conditionStr.split(",");
                for (String value : notValues) {
                    if (contextStr.equals(value.trim())) {
                        return false;
                    }
                }
                return true;
            case "gt":
            case ">":
                return compareNumeric(contextValue, conditionValue) > 0;
            case "lt":
            case "<":
                return compareNumeric(contextValue, conditionValue) < 0;
            case "gte":
            case ">=":
                return compareNumeric(contextValue, conditionValue) >= 0;
            case "lte":
            case "<=":
                return compareNumeric(contextValue, conditionValue) <= 0;
            default:
                log.warn("不支持的操作符: {}", operator);
                return false;
        }
    }
    
    /**
     * 数值比较
     */
    private int compareNumeric(Object contextValue, Object conditionValue) {
        try {
            Double contextNum = Double.valueOf(String.valueOf(contextValue));
            Double conditionNum = Double.valueOf(String.valueOf(conditionValue));
            return contextNum.compareTo(conditionNum);
        } catch (NumberFormatException e) {
            log.debug("数值比较失败，使用字符串比较: {} vs {}", contextValue, conditionValue);
            return String.valueOf(contextValue).compareTo(String.valueOf(conditionValue));
        }
    }

    @Override
    public boolean existsByFieldAndOperator(Long permissionId, String field, String operator, Long excludeId) {
        LambdaQueryWrapper<SysPermissionCondition> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysPermissionCondition::getPermissionId, permissionId)
               .eq(SysPermissionCondition::getField, field)
               .eq(SysPermissionCondition::getOperator, operator);
        
        if (excludeId != null) {
            wrapper.ne(SysPermissionCondition::getId, excludeId);
        }
        
        return count(wrapper) > 0;
    }

    // ============= 私有辅助方法 =============
    
    /**
     * 获取权限下条件的最大排序值
     */
    private Long getMaxSort(Long permissionId) {
        LambdaQueryWrapper<SysPermissionCondition> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysPermissionCondition::getPermissionId, permissionId)
               .orderByDesc(SysPermissionCondition::getSort)
               .last("LIMIT 1");
        
        SysPermissionCondition condition = getOne(wrapper);
        return condition != null && condition.getSort() != null ? condition.getSort() : 0L;
    }
    
    /**
     * 刷新相关缓存
     */
    private void refreshRelatedCache(SysPermissionCondition entity) {
        if (entity == null) {
            return;
        }
        
        // 刷新权限ID缓存
        if (entity.getPermissionId() != null) {
            refreshPermissionCache(entity.getPermissionId());
        }
        
        // 刷新表名缓存
        if (entity.getTableName() != null) {
            refreshTableCache(entity.getTableName());
        }
    }
}